<?php
/**
 * Created by PhpStorm.
 * User: zhan
 * Date: 2021/1/9  11:16
 */

namespace App\Services\Api;

use App\Models\ClassBaseInfo;
use App\Models\Coupon;
use App\Models\DiscountOrder;
use App\Models\UserCoupon;
use App\Models\UserCouponRecord;
use App\Models\UserVipInfo;
use App\Models\UserVipUseRecord;
use App\Services\Admin\Reservation;
use App\Models\UserSubscribe;
use App\Services\Api\UserIntegralServices;
use App\Traits\RetrunService;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\DB;

class CouponServices
{
    public function __construct(UserSubscribe $userSubscribe, UserIntegralServices $userIntegralServices)
    {
        $this->user_subscribe = $userSubscribe;
        $this->user_integral_services = $userIntegralServices;
    }

    public static function coupon_list($param)
    {
        $query = Coupon::where('is_opend', 1)
            ->where(function ($q) {
                $q->where('is_expiration', 2)
                    ->orWhere(function ($q) {
                        $q->where('is_expiration', 1)->where('expiration_time', '>=', date("Y-m-d H:i:s"));
                    });
            })->with([
                'my_coupon' => function ($q) use ($param) {
                    $q->select(['id', 'coupon_id', 'updated_at'])->where('user_id', $param['user_id']);
                },
                'store' => function ($q) {
                    $q->select(['id', 'store_name']);
                }
            ]);
        if (!empty($param['store_id'])) {
            $query->where('store_id', $param['store_id']);
        }
        return $query->paginate(15);
    }

    public static function coupon_info($coupon_id, $user_id)
    {
        return Coupon::where('id', $coupon_id)->with([
            'my_coupon' => function ($q) use ($user_id) {
                $q->select(['id', 'coupon_id', 'updated_at'])->where('user_id', $user_id);
            },
            'store' => function ($q) {
                $q->select(['id', 'store_name']);
            }
        ])
            ->first();
    }

    public static function add_user_coupon($param)
    {

        try {
            $query = Coupon::select([
                'id',
                'store_id',
                'coupon_title',
                'coupon_value',
                'is_expiration',
                'expiration_time',
                'coupon_code',
                'max_number'
            ]);

            if (!empty($param['coupon_id'])) {

                $userCouponObj = UserCouponRecord::where('user_id', $param['user_id'])->where('coupon_id', $param['coupon_id'])
                    ->first();

                $remarks_sql = $query->where('id', $param['coupon_id']);

                $remarks = $remarks_sql->value('coupon_title');

                $coupon_code_count = UserCouponRecord::sharedLock()->where('coupon_id', $param['coupon_id'])->count();

            } elseif (!empty($param['coupon_code'])) {

                $userCouponObj = UserCouponRecord::where('user_id', $param['user_id'])->where('coupon_code', $param['coupon_code'])
                    ->first();

                $remarks_sql = $query->where('coupon_code', $param['coupon_code']);

                $remarks = $remarks_sql->value('coupon_title');

                $coupon_code_count = UserCouponRecord::sharedLock()->where('coupon_code', $param['coupon_code'])->count();

            } else {

                throw new \Exception('參數不正確請檢查');

            }

            if (!empty($userCouponObj)) {

                throw new \Exception('已經領取過');

            }

            $couponObj = $query->first();

            if($coupon_code_count >= $couponObj->max_number)throw new \Exception('已超過最大領取數');
            //dd($couponObj);
            if ($couponObj->expiration_time < date("Y-m-d H:i;s") && $couponObj->is_expiration == 1) {
                throw new \Exception('時辰已過失效');
            }
            //user_id store_id type  status remarks class_base_info_id is_expiration expiration_time coupon_value
            $user_coupon_id = UserCoupon::insertGetId([
                'user_id' => $param['user_id'],
                'store_id' => $couponObj->store_id,
                'type' => 1,
                'status' => 1,
                'remarks' => $remarks,
                //'class_base_info_id'=>$remarks,
                'is_expiration' => $couponObj->is_expiration,
                'expiration_time' => $couponObj->expiration_time,
                'coupon_value' => $couponObj->coupon_value,
                'created_at' => date("Y-m-d H:i;s"),
            ]);

            $res = UserCouponRecord::insert([
                'user_id' => $param['user_id'],
                'store_id' => $couponObj->store_id,
                'coupon_id' => $couponObj->id,
                'user_coupon_id' => $user_coupon_id,
                'is_expiration' => $couponObj->is_expiration,
                'expiration_time' => $couponObj->expiration_time,
                'coupon_value' => $couponObj->coupon_value,
                'coupon_code' => $couponObj->coupon_code,
                'created_at' => date("Y-m-d H:i;s"),
            ]);

            if ($res) {
                return $res = [
                    'status' => true,
                    'msg' => '',
                ];
            }
            throw new \Exception('領取失敗,請聯繫客服');
        } catch (\Exception $e) {
            return $res = [
                'status' => false,
                'msg' => $e->getMessage(),
            ];
            //return RetrunService::fail($e -> getMessage());
        }

    }

    public static function my_user_coupon($param)
    {
        $query = UserCoupon::where('user_id', $param['user_id'])->with([
            'coupon' => function ($q) {
                $q->select(['id', 'coupon_title', 'is_expiration']);
            },
            'store' => function ($q) {
                $q->select(['id', 'store_name']);
            },
        ]);

        if (!empty($param['store_id'])) {
            $query->where('store_id', $param['store_id']);
        }

        if (!empty($param['status'])) {
            $query->where('status', $param['status']);
        }

        if (!empty($param['type'])) {
            $query->where('type', $param['type']);
        }

        if (!empty($param['is_expired'])) {
            if ($param['is_expired'] == 1) {
                $where[] = ['is_expiration', '1'];
                $where[] = ['expiration_time', '>=', date("Y-m-d 00:00:00", time())];

                $where[] = ['is_expiration', '=', '2', 'OR'];

                $query->where($where);
            } else {
                $query->where('is_expiration', '1')->where('expiration_time', '<=', date("Y-m-d 00:00:00", time()));
            }
        }

        return $query->orderBy('id', 'desc');
    }

    public static function my_user_coupon_info()
    {
        $id = request()->id ?? 0;

        if (empty($id)) throw new \Exception('id为空');

        $user_counpon = UserCoupon::with(['class_base_info' => function ($q) {
            $q->with('class_base');
        }])->where('user_id', auth()->user('api')->id)->where('id', $id)->first()->toArray();

        if (empty($user_counpon)) throw new \Exception('id有误');

        $class_time = (new UserSubscribe())->where('user_coupon_id', $id)->value('class_time');

        $result = [
            'class_base_name' => $user_counpon['class_base_info']['class_base']['class_name'] ?? '',
            'class_time' => $class_time ?? '',
            'updated_at' => $user_counpon['updated_at'] ?? '',
            'status' => $user_counpon['status'],
            'coupon_value' => $user_counpon['coupon_value'],
        ];

        return $result;
    }

    public function use_coupon($user_id, $coupon_id)
    {
        $user_coupon = UserCoupon::where('id', $coupon_id)->where('user_id', $user_id)->first();
        if ($user_coupon->is_expiration == 1) {
            if ($user_coupon->expiration_time < date("Y-m-d H:i:s")) {
                throw new \Exception('現金卷已過期!');
            }
        }

        $user_coupon->status = 2;
        $user_coupon->class_base_info_id = request()->all()['class_base_info_id'] ?? 0;
        $res = $user_coupon->save();
        return $res;
    }

    /**
     * 约课路由用于条件判断
     */
    public function create_subscribe_rule()
    {
        $input = request()->all();

        $baseInfo = (new ClassBaseInfo());

        $new_date = date('Y-m-d', $input['subscribe_time'] / 1000);

        $classBase = $baseInfo->with([
            'class_base' => function ($q) {
                $q->select(['id', 'class_name', 'class_price']);
            },
            'class_base_info_teacher',
            'classsroom' => function ($q) {
                $q->select(['id', 'numbering']);
            },
            'store' => function ($q) {
                $q->select(['id', 'store_name']);
            },
            'class_base_info_suspension',
            'quarterly'
        ])->find($input['class_base_info_id']);

        if (empty($classBase->class_time)) throw new \Exception('沒有設置上課時間');

        if(!empty($classBase->designated_date)) {
            //判断是否在时间范围内
            if (strpos($classBase->designated_date, $new_date) === false) {
                throw new \Exception('當天沒有該節課');
            }
        }

        $subscribe_time = strtotime($new_date);

        $time = explode('~', $classBase->class_time);

        $start_time = $subscribe_time + HisToS($time[0]);

        $end_time = $subscribe_time + HisToS($time[1]);

        $subscribe_time_date = date('Y-m-d', $subscribe_time);

        $open_an_appointment = Reservation::current_control_time($classBase->class_base_info_suspension->toArray(), $subscribe_time_date);

        if ($open_an_appointment == 0) {
            if ($classBase->is_display == -1) throw new \Exception('該課已關閉預約!');
        } else {
            //部分控制是否开启预约
            if ($open_an_appointment == -1) throw new \Exception('該課已關閉預約!');
        }

        if (time() > $start_time) throw new \Exception('已開課不能約，下次早點來哦');

        $start_time_select = "{$new_date} 00:00:00";

        $end_time_select = "{$new_date} 23:59:59";

        $class_status = [1,2,5,7];

        $class_subscribe_number = (new UserSubscribe)->ClassSubscribeNumber([$input['class_base_info_id']], $start_time_select, $end_time_select, $class_status);

        //已预约人数
        $class_subscribe_number = $class_subscribe_number[$input['class_base_info_id']]??0;

        if(!empty($classBase->start_before_minutes)) {
            //判断是否够人数开课,不够则不允许预约
            if (time() > ($start_time - ($classBase->start_before_minutes * 60))) {
                if ($class_subscribe_number < $classBase->minimum_number) throw new \Exception('該時段的課程不夠人數開課，請額外選擇其他課程');
            }
        }

        //判断是否该等级
        if (!empty($classBase->user_rank_id)) {
            if (!in_array(auth()->user('api')->user_rank_id, $classBase->user_rank_id)) throw new \Exception('等級未夠不能預約該課程!');
        }

        if ($classBase->quarterly->end_time < date("Y-m-d H:i:s")) throw new \Exception('已超過上課周期，不能預約');

        $week = date("w", $subscribe_time);

        if (empty($week)) $week = 7;

        if ($week != $classBase->getOriginal('class_week')) throw new \Exception('當天沒有該節課');

        $baseInfo = (new ClassBaseInfo());

        //計算6天內時間 有沒有預約過
        $seven_date = date("Y-m-d H:i:s", $subscribe_time + strtotime("+6 day"));
        $check_base_info_number = $this->user_subscribe->CheckRepeatClassInfoNumber($input['class_base_info_id'], date("Y-m-d H:i:s", $start_time), $seven_date, auth('api')->user()->id);
        if ($check_base_info_number > 0) throw new \Exception('請勿重複預約');

        $class_bass_info_teacher_arr = Reservation::class_bass_info_teacher_result($input['class_base_info_id'])->get()->toArray();

        $teacher = Reservation::class_bass_info_teacher_arr($class_bass_info_teacher_arr, $subscribe_time_date);

        if (empty($teacher['id'])) throw new \Exception('该时间没老师上课!');

        //有卷的時候判斷現金卷是否夠抵扣
        if (!empty($input['user_coupon_id'])) {

            $userCoupon = UserCoupon::where('id', $input['user_coupon_id'])
                ->where('user_id', auth('api')->user()->id)
                ->first();

            if (empty($userCoupon)) throw new \Exception('现金卷参数有误');

            $blance = $this->user_integral_services->available_integral(auth('api')->user()->id);

            if ($classBase->class_base->class_price > ($userCoupon->coupon_value + $blance)) throw new \Exception('積分與金額卷加起來不夠');

        }

        if (empty($input['original_subscribe_id']) && empty($input['user_coupon_id']) && empty($input['discount_order_id']) && empty($input['vip_id'])) {
            if ($this->user_integral_services->available_integral(auth('api')->user()->id) < ($classBase->class_base->class_price)) throw new \Exception('積分不足');
        }

        $rule_param = 0;

        $is_empty_rule = [
            'vip_id',
            'original_subscribe_id',
            'discount_order_id',
            'user_coupon_id',
        ];

        foreach ($input as $k => $v){
            if(in_array($k, $is_empty_rule) && !empty($v))$rule_param++;
        }

        if($rule_param > 1)throw new \Exception("現金卷，捆綁卷，vip，多個參數不允許并用");

        //补课操作 现金卷使用 捆綁卷預約不能同時傳參數
        $is_bool = 0;

        if (!empty($input['original_subscribe_id'])) $is_bool++;
        if (!empty($input['user_coupon_id'])) $is_bool++;
        if (!empty($input['discount_order_id'])) $is_bool++;

        if ($is_bool > 1) throw new \Exception('original_subscribe_id,user_coupon_id,discount_order_id只能傳一個參數');

        $result = [
            'classBase' => $classBase,
            'start_time' => $start_time,
            'end_time' => $end_time,
            'subscribe_time_date' => $subscribe_time_date,
            'teacher' => $teacher,
            'minimum_number'=>$classBase->minimum_number,                                   //最少人数开课
            'start_before_minutes_value'=>$classBase->start_before_minutes,                 //提前多少分钟检测
            'start_time_minutes'=>$start_time - ($classBase->start_before_minutes * 60)     //提前准确时间段判断
        ];

        return $result;
    }

    /**
     * 排满人
     * @param $start_time
     * @param $end_time
     */
    public function full_queue($start_time, $end_time)
    {
        DB::beginTransaction();
        $input = request()->all();

        //计算当前排位
        $queue = $this->user_subscribe
            //->select(['id','user_id'])
            ->where('class_base_info_id', $input['class_base_info_id'])
            ->where('subscribe_status', 1)
            ->where('class_time', date("Y-m-d H:i:s", $start_time))
            ->where('end_time', date("Y-m-d H:i:s", $end_time))
            ->count();

        $input['queue_number'] = $queue + 1;
        DB::commit();
        return $input;
    }

    /**
     * 补课操作
     * @param $classBase
     * @throws \Exception
     */
    public function make_up($classBase)
    {
        DB::beginTransaction();
        $input = request()->all();

        //补课验证积分规则
        $camp_subscribe_id = $input['original_subscribe_id'];
        $original_subscribe = UserSubscribe::where('id', $camp_subscribe_id)->first();

        if ($original_subscribe->subscribe_status != 6) {
            throw new \Exception('当前状态不能补课');
        }

        if ($original_subscribe->remedial_teaching_time < time()) {
            throw new \Exception('只能在请假15天内补课');
        }

        if ($original_subscribe->use_integral < $classBase->class_base->class_price) {
            throw new \Exception('只能选择不高于请假课程价值的课程');
        }

        $original_subscribe->subscribe_status = 7;
        $original_subscribe->save();
        DB::commit();
    }

    /**
     * 现金卷抵扣
     * @param $classBase
     * @param $start_time
     * @throws \Exception
     */
    public function original_subscribe($classBase, $start_time)
    {
        DB::beginTransaction();
        $input = request()->all();

        //如果有优惠券
        $userCoupon = UserCoupon::where('id', $input['user_coupon_id'])
            ->where('user_id', auth('api')->user()->id)
            ->first();

        //判断优惠券类型
        if (!empty($userCoupon)) {
            if ($userCoupon->status != 1) {
                throw new \Exception('優惠卷不可用');
            }
        } else {
            throw new \Exception('优惠券不存在');
        }

        if ($classBase->store->id != $userCoupon->store_id) {
            throw new \Exception('本優惠券不是對應門店');
        }

        $res = $this->use_coupon(auth('api')->user()->id, $input['user_coupon_id']);

        if (!$res) throw new \Exception('使用失败');

        DB::commit();

        return $classBase->class_base->class_price - $userCoupon->coupon_value;

    }

    /**
     * 捆綁卷使用
     */
    public function discount_meal()
    {
        DB::beginTransaction();
        $input = request()->all();

        $discount_order_id = $input['discount_order_id'];

        $discount_order = (new DiscountOrder())->where('id', $input['discount_order_id'])->where('user_id', auth()->user('api')->id)->select('id', 'discount_expired')->first();

        if (empty($discount_order->id)) throw new \Exception('該捆綁卷不存在!');

        if (date("Y-m-d H:i:s") > $discount_order->discount_expired) throw new \Exception('該捆綁卷已過期!');

        $where[] = ['discount_order_id', $discount_order_id];
        $where[] = ['class_base_info_id', $input['class_base_info_id']];
        $user_counon = UserCoupon::where($where)->first();

        if (empty($user_counon)) throw new \Exception('該捆綁卷預約不了該課程!');
        if ($user_counon->user_id != auth()->user('api')->id) throw new \Exception('非法操作!');
        if ($user_counon->status != 1) throw new \Exception('該捆綁卷已預約過了!');

        $user_counon->status = 2;
        $user_counon->save();

        //查询是否已用完
        $user_coupon_count = (new UserCoupon())->where('status', '2')->where('discount_order_id', $discount_order_id)->count();

        $user_coupon_total = (new UserCoupon())->where('discount_order_id', $discount_order_id)->count();

        if ($user_coupon_count == $user_coupon_total) {
            (new DiscountOrder())->where('id', $input['discount_order_id'])->update(['is_use_finish' => '2']);
        }

        DB::commit();
    }

    /**
     * vip 操作
     */
    public function vip($param, $class_name = '')
    {
        $where[] = ['user_id', auth()->user('api')->id];
        $where[] = ['vip_id', $param['vip_id']];
        $where[] = ['class_info_id', $param['class_base_info_id']];

        //操作vip详情
        $user_vip_info = UserVipInfo::where($where)->first();

        if(empty($user_vip_info))throw new \Exception('該vip不可預約或預約次數已用完');

        if(!empty($user_vip_info->is_restriction)){
            if(empty($user_vip_info->num)) throw new \Exception('該vip不可預約或預約次數已用完');
        }

        //判斷是否過期
        $vip_info = VipServices::info(auth()->user('api')->id, $param['vip_id']);

        if(empty($vip_info))throw new \Exception('請先購買vip');

        //会员卡超时了
        if(strtotime("{$vip_info->vip_maturity}") < time())throw new \Exception('該會員卡已過期');

        //看看是否到激活期
        if(!empty($vip_info->activate)){
            if(strtotime("{$vip_info->activate}") > time())throw new \Exception('會員卡為激活');
        }


        //記錄明細
        $user_use = (new UserVipUseRecord);
        $user_use->user_id = auth()->user('api')->id;
        $user_use->user_vip_id = $param['vip_id'];
        $user_use->user_vip_name = $vip_info->vip_title;
        $user_use->class_name = $class_name;
        $user_use->class_info_id = $param['class_base_info_id'];
        $user_use->is_restriction = $user_vip_info->is_restriction;
        if(!empty($user_vip_info->is_restriction)) {
            $user_use->before_num = $user_vip_info->num;
            $user_use->after_num = --$user_vip_info->num;
        }else{
            $user_use->before_num = 0;
            $user_use->after_num = 0;
        }
        $user_use->save();

        if(!empty($user_vip_info->is_restriction)) {
            //操作vip
            UserVipInfo::where($where)->decrement('num');
        }

        return $user_use->id;
    }
}
